<template>
  <el-form>
    <el-form-item label="SPU名称">
      <el-input
        placeholder="请输入SPU名称"
        v-model="spuParams.spuName"
      ></el-input>
    </el-form-item>
    <el-form-item label="SPU品牌">
      <el-select v-model="spuParams.tmId" placeholder="请选择" clearable>
        <el-option
          :label="trademark.tmName"
          :value="trademark.id"
          v-for="(trademark, index) in allTrademarkData"
          :key="trademark.id"
        >
        </el-option>
      </el-select>
    </el-form-item>
    <el-form-item label="SPU描述">
      <el-input
        placeholder="请输入SPU描述"
        type="textarea"
        v-model="spuParams.description"
      ></el-input>
    </el-form-item>
    <!-- 照片墙 -->
    <el-form-item label="SPU图片">
      <el-upload
        v-model:file-list="imgListData"
        action="/api/admin/product/fileUpload"
        list-type="picture-card"
        :on-preview="handlePictureCardPreview"
        :on-remove="handleRemove"
      >
        <el-icon><Plus /></el-icon>
      </el-upload>

      <el-dialog v-model="dialogVisible">
        <img w-full :src="dialogImageUrl" alt="Preview Image" />
      </el-dialog>
    </el-form-item>
    <!-- 销售属性 -->
    <el-form-item label="销售属性">
      <el-select
        v-model="unSelectAttrIdAndName"
        :placeholder="
          unSelectAttr.length > 0
            ? `还有${unSelectAttr.length}个属性未选择`
            : '已经没有了'
        "
        clearable
        style="margin-right: 20px"
      >
        <el-option
          :label="attr.name"
          v-for="(attr, index) in unSelectAttr"
          :key="attr.id"
          :value="`${attr.id}:${attr.name}`"
        >
        </el-option>
      </el-select>
      <el-button
        type="primary"
        :icon="Plus"
        :disabled="!unSelectAttrIdAndName"
        @click="addSalesAttr"
        >添加销售属性值</el-button
      >
    </el-form-item>
    <el-table border stripe style="margin: 20px 0" :data="hadSalesData">
      <el-table-column label="序号" type="index" align="center" width="80px">
      </el-table-column>
      <el-table-column label="属性名" prop="saleAttrName" width="100px">
      </el-table-column>
      <el-table-column label="属性值名称列表">
        <template #="{ row, $index }">
          <el-tag
            type="success"
            size="small"
            style="margin: 2px 5px"
            closable
            v-for="attrVal in row.spuSaleAttrValueList"
            :key="attrVal.id"
            @close="row.spuSaleAttrValueList.splice($index, 1)"
            >{{ attrVal.saleAttrValueName }}</el-tag
          >
          <!-- 编辑模式 -->
          <el-input
            v-if="row.flag"
            size="small"
            style="width: 90px"
            clearable
            placeholder="请输入属性值"
            v-model="row.inputValue"
            @blur="toLook(row)"
            :ref="(vc) => (inputArr[$index] = vc)"
          ></el-input>
          <!-- 查看模式 -->
          <el-button
            v-else
            size="small"
            :icon="Plus"
            @click="toEdit(row, $index)"
          ></el-button>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="120px">
        <template #="{ row, $index }">
          <el-button
            type="danger"
            size="small"
            :icon="Delete"
            @click="hadSalesData.splice(index, 1)"
          ></el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 按钮记得写在表单内! -->
    <el-button type="primary" size="default" @click="save">保存</el-button>
    <el-button @click="cancel">取消</el-button>
  </el-form>
</template>

<script setup lang="ts">
// 引入照片墙所需的
import { computed, ref, nextTick } from "vue";
import { Plus, Delete } from "@element-plus/icons-vue";
import type { UploadProps, UploadUserFile } from "element-plus";
import { ElMessage } from "element-plus";
import {
  reqAddOrUpdateSpu,
  reqAllTrademark,
  reqBaseSalesAttr,
  reqHadSalesAttr,
  reqImgList,
} from "@/api/product/spu/spu";

// 照片墙相关代码
const dialogImageUrl = ref("");
const dialogVisible = ref(false);
// 删除图片相关的回调
const handleRemove: UploadProps["onRemove"] = (uploadFile, uploadFiles) => {
  console.log(uploadFile, uploadFiles);
};
// 预览图片相关的回调
const handlePictureCardPreview: UploadProps["onPreview"] = (uploadFile) => {
  dialogImageUrl.value = uploadFile.url!;
  dialogVisible.value = true;
};

// 自定义事件
let emit = defineEmits(["changeScene"]);

// 存储服务器返回的数据
// 品牌数据
let allTrademarkData = ref([]);
// 照片墙数据
let imgListData = ref([]);
// 销售属性数据
let baseSalesData = ref([]);
// 已有销售属性数据
let hadSalesData = ref([]);

// 定义要发送给服务器的数据
let spuParams = ref<any>({});

// 定义未选择的销售属性的id和name
let unSelectAttrIdAndName = ref("");

// 拿到el-input框的实例
let inputArr = ref([]);

// 定义一个方法,方便父组件之后直接调用,row是父组件传过来的参数,是每一个SPU对象
const initSpuList = async (row) => {
  spuParams.value = row;
  let spu1 = reqAllTrademark();
  let spu2 = reqImgList(row.id);
  let spu3 = reqBaseSalesAttr();
  let spu4 = reqHadSalesAttr(row.id);
  let result = await Promise.all([spu1, spu2, spu3, spu4]);
  // 照片墙有固定的key值,key必须为name和url才能展示出图片,所以此处使用了数组的map方法来修改key值
  allTrademarkData.value = result[0];
  imgListData.value = result[1].map((item) => {
    return {
      name: item.imgName,
      url: item.imgUrl,
    };
  });
  baseSalesData.value = result[2];
  hadSalesData.value = result[3];
};

// 添加的方法
const initAddSpu = async (c3Id: string | number) => {
  // 注:要使用ref定义的响应式数据一定不要忘了加 value !!
  // 整理参数,新增需要三级分类的id(需要只要添加的SPU是给谁添加的)
  spuParams.value.category3Id = c3Id;
  let spu1 = reqAllTrademark();
  let spu2 = reqBaseSalesAttr();
  let result = await Promise.all([spu1, spu2]);
  allTrademarkData.value = result[0];
  baseSalesData.value = result[1];
};

// 对外暴露该方法(让父组件能拿到)
defineExpose({
  initSpuList,
  initAddSpu,
});

// 计算未被选择的销售属性
let unSelectAttr = computed(() => {
  // 使用数组的过滤方法,找出剩余的销售属性,filter方法返回的是布尔值
  // 真就过滤出来,假就不出来
  let result = baseSalesData.value.filter((item) => {
    return hadSalesData.value.every((item1) => {
      return item.name != item1.saleAttrName;
    });
  });
  return result;
});

// 点击添加属性值按钮的回调
const addSalesAttr = () => {
  // 整理数据
  let [baseSaleAttrId, saleAttrName] = unSelectAttrIdAndName.value.split(":");
  let newSalesAttr = { baseSaleAttrId, saleAttrName, spuSaleAttrValueList: [] };
  // 往数组中添加销售属性对象
  hadSalesData.value.push(newSalesAttr);
  // 清空输入框的值
  unSelectAttrIdAndName.value = "";
};

// 点击加号切换为编辑模式
const toEdit = (row, $index) => {
  row.flag = true;
  row.inputValue = "";
  nextTick(() => {
    inputArr.value[$index].focus();
  });
};

// 文本框失焦切换为查看模式
const toLook = (row) => {
  // 不允许文本框为空就添加属性值
  if (row.inputValue.trim() == "") {
    ElMessage({
      type: "error",
      message: "属性值不能为空",
    });
    return;
  }

  // 属性值不允许重复
  let repeated = row.spuSaleAttrValueList.find((item) => {
    return row.inputValue == item.saleAttrValueName;
  });

  if (repeated) {
    ElMessage({
      type: "error",
      message: "属性值不能重复",
    });
    row.inputValue = "";
    return;
  }

  row.flag = false;
  // 失焦时添加属性值
  // 整理数据(注:v-model不要绑错位置!!!)
  let newSalesAttrValue = {
    baseSaleAttrId: row.baseSaleAttrId,
    saleAttrValueName: row.inputValue,
  };
  // 添加到属性值数组里
  row.spuSaleAttrValueList.push(newSalesAttrValue);
  // 清空文本框中的值
  row.inputValue = "";
};

// 点击保存按钮的回调(修改SPU)
const save = async () => {
  // 整理参数
  // 照片墙的数据
  spuParams.value.spuImageList = imgListData.value.map((item) => {
    return {
      imgName: item.name,
      imgUrl: (item.response && item.response.data) || item.url,
    };
  });
  // 销售属性数据
  spuParams.value.spuSaleAttrList = hadSalesData.value;
  try {
    await reqAddOrUpdateSpu(spuParams.value);
    ElMessage({
      type: "success",
      message: spuParams.value.id ? "修改成功" : "添加成功",
    });
    emit("changeScene", {
      scenes: 0,
      whichOne: spuParams.value.id ? "update" : "add",
    });
    // 重置数据
    resetData();
  } catch (error) {
    ElMessage({
      type: "error",
      message: spuParams.value.id ? "修改失败" : "添加失败",
    });
  }
};

// 点击取消按钮的回调
const cancel = () => {
  // 切换场景
  emit("changeScene", {
    scenes: 0,
    flag: spuParams.value.id ? "update" : "add",
  });
  // 重置数据
  resetData();
};

// 重置数据的方法
const resetData = () => {
  spuParams.value = {};
  imgListData.value = [];
  baseSalesData.value = [];
};
</script>

<style scoped>
</style>